package com.wx.jvm.oom;

import lombok.extern.slf4j.Slf4j;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 直接内存 OOM
 *
 * @author wang.xun
 * @date 2023/08/14
 */
@Slf4j
public class DirectMemory {


    static void malloc() {
        AtomicInteger count = new AtomicInteger(0);

        /*
          直接申请 theUnsafe 会比较当前的类加载器是否为bootstrap加载器
          如果不是就是报错
          Exception in thread "main" java.lang.SecurityException: Unsafe
          	at sun.misc.Unsafe.getUnsafe(Unsafe.java:90)
          	at com.wx.jvm.oom.DirectMemory.malloc(DirectMemory.java:14)
          	at com.wx.jvm.oom.DirectMemory.main(DirectMemory.java:18)
         */
        //Unsafe unsafe = Unsafe.getUnsafe();
        // 需要利用反射来获取 Unsafe 实例
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            Unsafe unsafe = (Unsafe) theUnsafe.get(null);
            // 开辟1MB的直接内存空间
            ArrayList<Object> objects = new ArrayList<>();

            while(true){

                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 * 1024);
                objects.add(byteBuffer);
                /*
                    反射获取unsafe 不受 -XX:MaxDirectMemorySize=10M 控制
                    只和操作系统的内存相关
                 */
                //long l = unsafe.allocateMemory(1024 * 1024 );
                //objects.add(l);
                count.getAndIncrement();
                log.info("申请了：{}MB空间了",count);
            }


        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }

    public static void main(String[] args) {
        DirectMemory.malloc();
    }
}
